﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace One.Framework.Util
{
    /// <summary>
    /// 문자열
    /// </summary>
    public class StringHelper
    {
        /// <summary>
        /// Null값 처리
        /// </summary>
        /// <param name="data">처리대상 개체</param>
        /// <returns>문자열 변환 반환</returns>
        public static string GetNull(Object data)
        {
            return data == null ? String.Empty : data.ToString();
        }

        /// <summary>
        /// Null값 기본값 치환 처리
        /// </summary>
        /// <param name="data">처리대상 개체</param>
        /// <param name="defaultValue">반환할 기본값 문자열</param>
        /// <returns>문자열 변환 반환</returns>
        public static string GetNull(Object data, String defaultValue)
        {
            return data == null ? defaultValue : data.ToString();
        }

        /// <summary>
        /// Null값 개체 기본값 개체로 반환 처리
        /// </summary>
        /// <param name="data">처리대상 개체</param>
        /// <param name="defaultValue">기본 반환 개체</param>
        /// <returns>개체반환</returns>
        public static object GetNull(Object data, Object defaultValue)
        {
            return data == null ? defaultValue : data;
        }

        /// <summary>
        /// Null값 DateTime 개체 문자열로 반환 처리
        /// </summary>
        /// <param name="data">처리대상 개체</param>
        /// <returns>개체반환</returns>
        public static string GetNullDate(Object data)
        {
            return data == null ? String.Empty : data.ToString();
        }

        /// <summary>
        /// DB NULL값 문자열 변환 처리
        /// </summary>
        /// <param name="data">처리대상 개체</param>
        /// <returns>문자열 변환 반환</returns>
        public static string GetDbNull(Object data)
        {
            return data == DBNull.Value ? String.Empty : data.ToString();
        }

        /// <summary>
        /// DB NULL값 기본값 변환 처리
        /// </summary>
        /// <param name="data">처리대상 개체</param>
        /// <param name="defaultValue">기본변환 문자열</param>
        /// <returns>문자열 변환 반환</returns>
        public static string GetDbNull(Object data, String defaultValue)
        {
            return data == DBNull.Value ? defaultValue : data.ToString();
        }

        /// <summary>
        /// DB NULL값 기본값 변환 처리
        /// </summary>
        /// <param name="data">처리대상 개체</param>
        /// <param name="defaultValue">기본변환개체</param>
        /// <returns>기본개체로 변환 반환</returns>
        public static object GetDbNull(Object data, Object defaultValue)
        {
            return data == DBNull.Value ? defaultValue : data;
        }

        /// <summary>
        /// int형 문자열을 Int형으로 변환
        /// </summary>
        /// <param name="intString">int형 문자열</param>
        /// <returns>integer값 반환</returns>
        public static int ConvertStringToInteger(string intString)
        {
            int newIntString = 0;

            intString = intString.Replace(",", "");

            if (intString.Length > 0)
            {
                newIntString = int.Parse(intString.Trim());
            }

            return newIntString;
        }

        /// <summary>
        /// Double형 문자열을 Double형으로 변환
        /// </summary>
        /// <param name="intString">Double형 문자열</param>
        /// <returns>Double 값 반환</returns>
        public static double ConvertStringToDouble(string intString)
        {
            double newDBLString = 0;

            intString = intString.Replace(",", "");

            if (intString.Length > 0)
            {
                newDBLString = Double.Parse(intString.Trim());
            }

            return newDBLString;
        }

        /// <summary>
        /// 문자열 자르기
        /// </summary>
        /// <param name="strText"></param>
        /// <param name="intCutNum"></param>
        /// <returns></returns>
        public static string CutStr(String strText, Int32 intCutNum)
        {
            string stringReturnVal = string.Empty;

            System.Text.Encoding EncodingIns = System.Text.Encoding.Default;

            byte[] byteTemp = EncodingIns.GetBytes(strText);

            if (byteTemp.Length > intCutNum)
            {
                stringReturnVal = EncodingIns.GetString(byteTemp, 0, intCutNum) + "...";

                while (stringReturnVal.IndexOf("?") > -1)
                {
                    intCutNum++;

                    stringReturnVal = EncodingIns.GetString(byteTemp, 0, intCutNum) + "...";
                }
            }
            else
                stringReturnVal = EncodingIns.GetString(byteTemp, 0, byteTemp.Length);

            return stringReturnVal;
        }


        /// <summary>
        /// 구분자를 이용한 배열목록 반환함수
        /// </summary>
        /// <param name="list">목록</param>
        /// <param name="seperator">구분자</param>
        /// <returns>배열목록</returns>
        public static string[] GetSeperatorList(string list, string seperator)
        {
            if (!string.IsNullOrEmpty(list))
            {
                System.Text.RegularExpressions.Regex seperate = new System.Text.RegularExpressions.Regex(seperator);
                string[] strList = seperate.Split(list);
                return strList;
            }
            else
                return null;
        }

        /// <summary>
        /// 전화번호자리별 정보 반환 함수
        /// </summary>
        /// <param name="telephoneNumber">전화번호(011-555-5555,02-555-8888)</param>
        /// <returns>전화번호 자릿수별 배열정보</returns>
        public static string[] GetTelephoneNumbers(string telephoneNumber)
        {
            System.Text.RegularExpressions.Regex telSeperator = new System.Text.RegularExpressions.Regex("-");
            string[] numbers = telSeperator.Split(telephoneNumber);
            return numbers;
        }

        /// <summary>
        /// 메일링 수신자 리스트 메일주소 배열 반환 함수
        /// </summary>
        /// <param name="emailList">메일주소목록(구분자 ; 로 표기)</param>
        /// <returns>메일주소배열</returns>
        public static string[] GetEmailAddress(string emailList)
        {
            System.Text.RegularExpressions.Regex telSeperator = new System.Text.RegularExpressions.Regex(";");
            string[] emails = telSeperator.Split(emailList);
            return emails;
        }

        /// <summary>
        /// Json 데이터로 변환
        /// </summary>
        /// <param name="table"></param>
        /// <returns></returns>
        private static List<Dictionary<string, object>> RowsToDictionary(System.Data.DataTable table)
        {
            List<Dictionary<string, object>> objs = new List<Dictionary<string, object>>();
            foreach (System.Data.DataRow dr in table.Rows)
            {
                Dictionary<string, object> drow = new Dictionary<string, object>();
                for (int i = 0; i < table.Columns.Count; i++)
                {
                    drow.Add(table.Columns[i].ColumnName, dr[i]);
                }
                objs.Add(drow);
            }
            return objs;
        }

        /// <summary>
        /// Json 데이터로 변환
        /// </summary>
        /// <param name="table">DataTable</param>
        /// <returns></returns>
        public static Dictionary<string, object> ToJson(System.Data.DataTable table)
        {
            Dictionary<string, object> dic = new Dictionary<string, object>();
            dic.Add(table.TableName, RowsToDictionary(table));
            return dic;
        }

        /// <summary>
        /// Json 데이터로 변환
        /// </summary>
        /// <param name="ds">DataSet</param>
        /// <returns></returns>
        public static Dictionary<string, object> ToJson(System.Data.DataSet ds)
        {
            Dictionary<string, object> dic = new Dictionary<string, object>();
            foreach (System.Data.DataTable table in ds.Tables)
            {
                dic.Add(table.TableName, RowsToDictionary(table));
            }
            return dic;
        }

        /// <summary>
        /// Guid 생성 후 16요소 바이트 문자열로 반환
        /// </summary>
        /// <returns></returns>
        public static string NewGuidToString()
        {
            Guid guid = Guid.NewGuid();
            byte[] b16 = guid.ToByteArray();
            return new Guid(b16).ToString();
        }

        /// <summary>
        /// Base64로 문자열을 인코딩
        /// </summary>
        /// <param name="input">문자열</param>
        /// <returns>인코딩된 문자열 반환</returns>
        public static string Base64StringEncode(string input)
        {
            byte[] encbuff = System.Text.Encoding.UTF8.GetBytes(input);
            return Convert.ToBase64String(encbuff);
        }

        /// <summary>
        /// Base64로 문자열을 디코딩
        /// </summary>
        /// <param name="input">Base64로 인코딩된 문자열</param>
        /// <returns>인코딩된 문자열 디코딩 반환</returns>
        public static string Base64StringDecode(string input)
        {
            byte[] decbuff = Convert.FromBase64String(input);
            return System.Text.Encoding.UTF8.GetString(decbuff);
        }

        /// <summary>
        /// A case insenstive replace function.
        /// </summary>
        /// <param name="input">The string to examine.</param>
        /// <param name="newValue">The value to replace.</param>
        /// <param name="oldValue">The new value to be inserted</param>
        /// <returns>A string</returns>
        public static string CaseInsenstiveReplace(string input, string newValue, string oldValue)
        {
            System.Text.RegularExpressions.Regex regEx = new System.Text.RegularExpressions.Regex(oldValue,
               System.Text.RegularExpressions.RegexOptions.IgnoreCase | System.Text.RegularExpressions.RegexOptions.Multiline);
            return regEx.Replace(input, newValue);
        }

        /// <summary>
        /// Replaces the first occurence of a string with the replacement value. The Replace
        /// is case senstive
        /// </summary>
        /// <param name="input">The string to examine</param>
        /// <param name="oldValue">The value to replace</param>
        /// <param name="newValue">the new value to be inserted</param>
        /// <returns>A string</returns>
        public static string ReplaceFirst(string input, string oldValue, string newValue)
        {
            System.Text.RegularExpressions.Regex regEx = new System.Text.RegularExpressions.Regex(oldValue, System.Text.RegularExpressions.RegexOptions.Multiline);
            return regEx.Replace(input, newValue, 1);
        }

        /// <summary>
        /// Replaces the last occurence of a string with the replacement value.
        /// The replace is case senstive.
        /// </summary>
        /// <param name="input">The string to examine</param>
        /// <param name="oldValue">The value to replace</param>
        /// <param name="newValue">the new value to be inserted</param>
        /// <returns>A string</returns>
        public static string ReplaceLast(string input, string oldValue, string newValue)
        {
            int index = input.LastIndexOf(oldValue);
            if (index < 0)
            {
                return input;
            }
            else
            {
                StringBuilder sb = new StringBuilder(input.Length - oldValue.Length + newValue.Length);
                sb.Append(input.Substring(0, index));
                sb.Append(newValue);
                sb.Append(input.Substring(index + oldValue.Length,
                   input.Length - index - oldValue.Length));

                return sb.ToString();
            }
        }

        /// <summary>
        /// 문자 필터링
        /// </summary>
        /// <param name="input">문자열</param>
        /// <param name="filterWords">필터 데이터</param>
        /// <returns>A string.</returns>
        public static string FilterWords(string input, params string[] filterWords)
        {
            return FilterWords(input,
               char.MinValue, filterWords);
        }

        /// <summary>
        /// Removes all the words passed in the filter words 
        /// parameters. The replace is NOT case
        /// sensitive.
        /// </summary>
        /// <param name="input">The string to search.</param>
        /// <param name="mask">A character that is inserted for each 
        /// letter of the replaced word.</param>
        /// <param name="filterWords">The words to 
        // repace in the input string.</param>
        /// <returns>A string.</returns>
        public static string FilterWords(string input, char mask,
           params string[] filterWords)
        {
            string stringMask = mask == char.MinValue ?
               string.Empty : mask.ToString();
            string totalMask = stringMask;

            foreach (string s in filterWords)
            {
                System.Text.RegularExpressions.Regex regEx = new System.Text.RegularExpressions.Regex(s,
                   System.Text.RegularExpressions.RegexOptions.IgnoreCase | System.Text.RegularExpressions.RegexOptions.Multiline);

                if (stringMask.Length > 0)
                {
                    for (int i = 1; i < s.Length; i++)
                        totalMask += stringMask;
                }

                input = regEx.Replace(input, totalMask);

                totalMask = stringMask;
            }

            return input;
        }

        /// <summary>
        /// 새줄(\n)과 리턴(\r) 기호 제거
        /// </summary>
        /// <param name="input">문자열</param>
        /// <returns>제거된 문자열 반환</returns>
        public static string RemoveNewLines(string input)
        {
            return RemoveNewLines(input, false);
        }

        /// <summary>
        /// 새줄(\n)과 리턴(\r) 기호 제거
        /// </summary>
        /// <param name="input">문자열</param>
        /// <param name="addSpace">true이면 공백추가</param>
        /// <returns>제거된 문자열 반환</returns>
        public static string RemoveNewLines(string input, bool addSpace)
        {
            string replace = string.Empty;
            if (addSpace)
                replace = " ";

            string pattern = @"[\r|\n]";
            System.Text.RegularExpressions.Regex regEx = new System.Text.RegularExpressions.Regex(pattern,
               System.Text.RegularExpressions.RegexOptions.IgnoreCase | System.Text.RegularExpressions.RegexOptions.Multiline);

            return regEx.Replace(input, replace);
        }

        /// <summary>
        /// 문자열을 거꾸로 변환
        /// </summary>
        /// <param name="input">문자열</param>
        /// <returns>거꾸로 변환된 문자열 반환</returns>
        public static string Reverse(string input)
        {
            char[] reverse = new char[input.Length];
            for (int i = 0, k = input.Length - 1; i < input.Length; i++, k--)
            {
                if (char.IsSurrogate(input[k]))
                {
                    reverse[i + 1] = input[k--];
                    reverse[i++] = input[k];
                }
                else
                {
                    reverse[i] = input[k];
                }
            }
            return new System.String(reverse);
        }

        /// <summary>
        /// Converts a string to sentence case.
        /// </summary>
        /// <param name="input">The string to convert.</param>
        /// <returns>A string</returns>
        public static string SentenceCase(string input)
        {
            if (input.Length < 1)
                return input;

            string sentence = input.ToLower();
            return sentence[0].ToString().ToUpper() +
               sentence.Substring(1);
        }

        /// <summary>
        /// Converts all spaces to HTML non-breaking spaces
        /// </summary>
        /// <param name="input">The string to convert.</param>
        /// <returns>A string</returns>
        public static string SpaceToNbsp(string input)
        {
            string space = " ";
            return input.Replace(" ", space);
        }

        /// <summary>
        /// Removes all HTML tags from the passed string
        /// </summary>
        /// <param name="input">The string whose 
        /// values should be replaced.</param>
        /// <returns>A string.</returns>
        public static string StripTags(string input)
        {
            System.Text.RegularExpressions.Regex stripTags = new System.Text.RegularExpressions.Regex("<(.|\n)+?>");
            return stripTags.Replace(input, "");
        }

        /// <summary>
        /// Converts a string to title case.
        /// </summary>
        /// <param name="input">The string to convert.</param>
        /// <returns>A string.</returns>
        public static string TitleCase(string input)
        {
            return TitleCase(input, true);
        }

        /// <summary>
        /// Converts a string to title case.
        /// </summary>
        /// <param name="input">The string to convert.</param>
        /// <param name="ignoreShortWords">If true, 
        /// does not capitalize words like
        /// "a", "is", "the", etc.</param>
        /// <returns>A string.</returns>
        public static string TitleCase(string input,
           bool ignoreShortWords)
        {
            List<string> ignoreWords = null;
            if (ignoreShortWords)
            {
                //TODO: Add more ignore words?
                ignoreWords = new List<string>();
                ignoreWords.Add("a");
                ignoreWords.Add("is");
                ignoreWords.Add("was");
                ignoreWords.Add("the");
            }

            string[] tokens = TrimIntraWords(input).Split(' ');
            StringBuilder sb = new StringBuilder(input.Length);
            foreach (string s in tokens)
            {
                if (ignoreShortWords == true
                    && s != tokens[0]
                    && ignoreWords.Contains(s.ToLower()))
                {
                    sb.Append(s + " ");
                }
                else
                {
                    sb.Append(s[0].ToString().ToUpper());
                    sb.Append(s.Substring(1).ToLower());
                    sb.Append(" ");
                }
            }

            return sb.ToString().Trim();
        }

        /// <summary>
        /// 단어 사이에 공백을 제거
        /// </summary>
        /// <param name="input">문자열</param>
        /// <returns>공백 제거된 문자열 반환</returns>
        public static string TrimIntraWords(string input)
        {
            System.Text.RegularExpressions.Regex regEx = new System.Text.RegularExpressions.Regex(@"[\s]+");
            return regEx.Replace(input, " ");
        }

        /// <summary>
        /// Converts new line(\n) and carriage return(\r) symbols to
        /// HTML line breaks.
        /// </summary>
        /// <param name="input">The string to convert.</param>
        /// <returns>A string.</returns>
        public static string NewLineToBreak(string input)
        {
            System.Text.RegularExpressions.Regex regEx = new System.Text.RegularExpressions.Regex(@"[\n|\r]+");
            return regEx.Replace(input, "<br />");
        }

        /// <summary>
        /// 문자열을 래핑 또는 공백에 새줄
        /// </summary>
        /// <param name="input">문자열</param>
        /// <param name="charCount">문자갯수</param>
        /// <returns>문자열 반환</returns>
        public static string WordWrap(string input, int charCount)
        {
            return WordWrap(input, charCount,
               false, Environment.NewLine);
        }

        /// <summary>
        /// 문자열을 래핑 또는 공백에 새줄
        /// </summary>
        /// <param name="input">문자열</param>
        /// <param name="charCount">문자갯수</param>
        /// <param name="cutOff">If true, will break in 
        /// the middle of a word.</param>
        /// <returns>A string.</returns>
        public static string WordWrap(string input, int charCount, bool cutOff)
        {
            return WordWrap(input, charCount,
               cutOff, Environment.NewLine);
        }

        /// <summary>
        /// Wraps the passed string at the total number 
        /// of characters (if cuttOff is true)
        /// or at the next whitespace (if cutOff is false).
        /// Uses the passed breakText
        /// for lineBreaks.
        /// </summary>
        /// <param name="input">The string to wrap.</param>
        /// <param name="charCount">The number of 
        /// characters per line.</param>
        /// <param name="cutOff">If true, will break in 
        /// the middle of a word.</param>
        /// <param name="breakText">The line break text to use.</param>
        /// <returns>A string.</returns>
        public static string WordWrap(string input, int charCount,
           bool cutOff, string breakText)
        {
            StringBuilder sb = new StringBuilder(input.Length + 100);
            int counter = 0;

            if (cutOff)
            {
                while (counter < input.Length)
                {
                    if (input.Length > counter + charCount)
                    {
                        sb.Append(input.Substring(counter, charCount));
                        sb.Append(breakText);
                    }
                    else
                    {
                        sb.Append(input.Substring(counter));
                    }
                    counter += charCount;
                }
            }
            else
            {
                string[] strings = input.Split(' ');
                for (int i = 0; i < strings.Length; i++)
                {
                    // added one to represent the space.
                    counter += strings[i].Length + 1;
                    if (i != 0 && counter > charCount)
                    {
                        sb.Append(breakText);
                        counter = 0;
                    }

                    sb.Append(strings[i] + ' ');
                }
            }
            // to get rid of the extra space at the end.
            return sb.ToString().TrimEnd();
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="items"></param>
        /// <param name="sort"></param>
        /// <returns></returns>
        public static string[] RemoveDups(string[] items, bool sort)
        {
            System.Collections.ArrayList noDups = new System.Collections.ArrayList();
            for (int i = 0; i < items.Length; i++)
            {

                if ((!noDups.Contains(items[i].Trim())) && ((items[i].Trim() != "")))
                {
                    noDups.Add(items[i].Trim());
                }
            }

            //sorts list alphabetically
            if (sort) noDups.Sort();
            string[] uniqueItems = new String[noDups.Count];
            noDups.CopyTo(uniqueItems);
            return uniqueItems;
        }

        /// <summary>
        /// 공백제거
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public static string RemoveSpace(string input)
        {
            int start = 0;
            int num = 0;
            string tmp = input;
            while (tmp.IndexOf(" ") > 0)
            {
                num = tmp.IndexOf(" ");
                string tmp1 = tmp.Substring(0, num);
                start = num + 1;
                tmp1 += tmp.Substring(num + 1);
                tmp = tmp1;
            } return tmp;
        }
    }
}
